<template>
  <div class="router-history">
    <el-tabs
      v-model="activeValue"
      :closable="!(historys.length === 1 && $route.name === defaultRouter)"
      type="card"
      @contextmenu.prevent="openContextMenu($event)"
      @tab-change="changeTab"
      @tab-remove="removeTab"
    >
      <el-tab-pane
        v-for="item in historys"
        :key="name(item)"
        :label="item.meta.title"
        :name="name(item)"
        :tab="item"
      >
        <template #label>
          <span
            :tab="item"
            :style="{
              color: activeValue === name(item) ? '#4D70FF' : '#333',
            }"
          ><i
             class="dot"
             :style="{
               backgroundColor:
                 activeValue === name(item) ? '#4D70FF' : '#ddd',
             }"
           />
            {{ item.meta.title }}</span>
        </template>
      </el-tab-pane>
    </el-tabs>
    <ul
      v-show="contextMenuVisible"
      :style="{ left: left + 'px', top: top + 'px' }"
      class="contextmenu"
    >
      <li @click="closeAll">关闭所有</li>
      <li @click="closeLeft">关闭左侧</li>
      <li @click="closeRight">关闭右侧</li>
      <li @click="closeOther">关闭其他</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HistoryComponent',
}
</script>

<script setup>
import { computed, onUnmounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useUserStore } from '@/store/modules/user'
import { useHallRouterStore } from '@/store/modules/hallRouter'

const route = useRoute()
const router = useRouter()
const userStore = useUserStore()
const hallRouterStore = useHallRouterStore()


const defaultRouter = computed(() => hallRouterStore.defaultRouter)
const historys = ref([])
const historyMap = ref({})
const activeValue = ref('')
const contextMenuVisible = ref(false)

const left = ref(0)
const top = ref(0)
const clickTab = ref('')


const getFmtString = (item) => {
  return item.name + JSON.stringify(item.query) + JSON.stringify(item.params)
}

const name = (item) => {
  const result = item.name + JSON.stringify(item.query) + JSON.stringify(item.params)
  return result
}

const openContextMenu = (e) => {
  let id = ''
  if (e.srcElement.nodeName === 'SPAN') {
    id = e.srcElement.offsetParent.id
  } else {
    id = e.srcElement.id
  }
  if (id) {
    contextMenuVisible.value = true
    left.value = e.clientX
    top.value = e.clientY
    clickTab.value = id.substring(4)
  }
}

const changeTab = (name) => {
  const tab = historyMap.value[name]
  router.push({
    name: tab.name,
    query: tab.query,
    params: tab.params,
  })
}

const removeTab = (tab) => {
  const index = historys.value.findIndex(
    (item) => getFmtString(item) === tab
  )
  if (getFmtString(route) === tab) {
    if (historys.value.length === 1) {
      router.push({ name: defaultRouter.value })
    } else {
      if (index < historys.value.length - 1) {
        router.push({
          name: historys.value[index + 1].name,
          query: historys.value[index + 1].query,
          params: historys.value[index + 1].params,
        })
      } else {
        router.push({
          name: historys.value[index - 1].name,
          query: historys.value[index - 1].query,
          params: historys.value[index - 1].params,
        })
      }
    }
  }
  historys.value.splice(index, 1)
}

const closeAll = () => {
  historys.value = []
  router.push({ name: defaultRouter.value })
  sessionStorage.setItem('historys', JSON.stringify(historys.value))
}

const closeLeft = () => {
  let clickRoute
  const clickIndex = historys.value.findIndex((item) => {
    if (getFmtString(item) === clickTab.value) {
      clickRoute = item
    }
    return getFmtString(item) === clickTab.value
  })
  const activeIndex = historys.value.findIndex(
    (item) => getFmtString(item) === activeValue.value
  )
  historys.value.splice(0, clickIndex)
  if (clickIndex > activeIndex) {
    router.push(clickRoute)
  }
  sessionStorage.setItem('historys', JSON.stringify(historys.value))
}

const closeRight = () => {
  let clickRoute
  const clickIndex = historys.value.findIndex((item) => {
    if (getFmtString(item) === clickTab.value) {
      clickRoute = item
    }
    return getFmtString(item) === clickTab.value
  })
  const activeIndex = historys.value.findIndex(
    (item) => getFmtString(item) === activeValue.value
  )
  historys.value.splice(clickIndex + 1, historys.value.length)
  if (clickIndex < activeIndex) {
    router.push(clickRoute)
  }
  sessionStorage.setItem('historys', JSON.stringify(historys.value))
}

const closeOther = () => {
  let clickRoute
  historys.value = historys.value.filter((item) => {
    if (getFmtString(item) === clickTab.value) {
      clickRoute = item
    }
    return getFmtString(item) === clickTab.value
  })
  router.push(clickRoute)
  sessionStorage.setItem('historys', JSON.stringify(historys.value))
}



//监听值变化
watch(() => historys.value, () => {
  sessionStorage.setItem('historys', JSON.stringify(historys.value))
  historyMap.value = {}
  historys.value.forEach((item) => {
    historyMap.value[getFmtString(item)] = item
  })
}, {
  deep: true
})

watch(() => route, (to, now) => {
  setTab(to)
}, { deep: true })

const setTab = (route) => {
  if (!historys.value.some((item) => isSame(item, route))) {
    const obj = {}
    obj.name = route.name
    obj.meta = { ...route.meta }
    delete obj.meta.matched
    obj.query = route.query
    obj.params = route.params
    historys.value.push(obj)
  }
  activeValue.value = getFmtString(route)
  window.sessionStorage.setItem('activeValue', getFmtString(route))
}

const isSame = (route1, route2) => {
  if (route1.name !== route2.name) {
    return false
  }
  if (Object.keys(route1.query).length !== Object.keys(route2.query).length || Object.keys(route1.params).length !== Object.keys(route2.params).length) {
    return false
  }
  for (const key in route1.query) {
    if (route1.query[key] !== route2.query[key]) {
      return false
    }
  }
  for (const key in route1.params) {
    if (route1.params[key] !== route2.params[key]) {
      return false
    }
  }
  return true
}

watch(() => contextMenuVisible.value, () => {
  if (contextMenuVisible.value) {
    document.body.addEventListener('click', () => {
      contextMenuVisible.value = false
    })
  } else {
    document.body.removeEventListener('click', () => {
      contextMenuVisible.value = false
    })
  }
})



//初始化
const initPage = () => {
  historys.value = JSON.parse(sessionStorage.getItem('historys')) || []
  activeValue.value = window.sessionStorage.getItem('activeValue')
  setTab(route)
}
initPage()


</script>

<style lang="scss" scoped>
.dot {
  content: "";
  width: 9px;
  height: 9px;
  margin-right: 8px;
  display: inline-block;
  border-radius: 50%;
  transition: background-color 0.2s;
}

</style>

<style lang="scss">
.router-history{
  .el-tabs{
    .el-tabs__header {
      margin: 0px 0 0 0;
    }
  }
}

.contextmenu {
  width: 100px;
  margin: 0;
  border: 1px solid #ccc;
  background: #fff;
  z-index: 3000;
  position: fixed;
  list-style-type: none;
  padding: 5px 0;
  border-radius: 4px;
  font-size: 14px;
  color: #333;
  box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2);
}

.contextmenu li {
  margin: 0;
  padding: 7px 16px;
}
.contextmenu li:hover {
  background: #f2f2f2;
  cursor: pointer;
}

</style>